package com.tul.exercise.base.java8.stream.collect;

import com.google.common.collect.Multiset;
import com.tul.exercise.base.java8.stream.base.Artist;
import com.tul.exercise.base.java8.stream.base.Dish;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Stream的 collect操作
 *
 * @author liang
 */
public class CollectTest {

    @Test
    @DisplayName("collect(toList())操作")
    public void test01() {

        // 根据基本类型序列创建list
        List<Integer> list = Stream.of(1, 2, 3, 4).collect(Collectors.toList());

        // 根据对象类型序列创建list
        List<Artist> artists = Stream.of(new Artist("Tu Liang","China"),
                    new Artist("Zhang San","China"))
                .collect(Collectors.toList());


        // 根据其他流创建list
        List<Artist> artists1 = Artist.createArtists(100).stream()
                .filter(Artist::isBank)
                .collect(Collectors.toList());
    }

    @Test
    @DisplayName("collect(toSet())操作")
    public void test02() {
        List<Artist> artists = Artist.createArtists(10);
        Set<Artist> set = artists.stream().collect(Collectors.toSet());
        set.stream().forEach(System.out::println);

        Stream.of(1, 2, 3, 3, 4).collect(Collectors.toSet())
                .stream().forEach(System.out::println);

        // 将Arttis列表中的from抽出到集合中
        Set<String> fromSet = artists.stream()
                .map(artist -> artist.getFrom())
                .collect(Collectors.toSet());

        System.out.println(fromSet);
    }

    @Test
    @DisplayName("collect(toMap())操作")
    public void test03() {
        List<Artist> artists = Artist.createArtists(3);

        // Artist转化为Map<id, from>
        Map<String, String> map = artists.stream().collect(Collectors.toMap(
                Artist::getId,
                (Artist a)->a.getFrom()
        ));
        System.out.println(map);

        // Artist转化为Map<id, Artist>
        Map<String, Artist> concurrentMap = artists.stream()
                .collect(Collectors.toConcurrentMap(
                        Artist::getId,
                        artist -> artist));
        System.out.println(concurrentMap);



        artists = Artist.createArtists(10);
        // 从一个流中创建映射的代码会在存在重复的键时抛出异常。
        // 增加toMap方法合并重复
        Map<String, Artist> nameMap = artists.stream().collect(Collectors.toMap(
                Artist::getName, Function.identity(),(a1, a2)->a2));

        System.out.println(nameMap);

    }

    @Test
    @DisplayName("collect(toCollection())操作")
    public void test04() {
        List<Artist> artists = Artist.createArtists(10);

        LinkedHashSet<Artist> set = artists.stream()
                .collect(Collectors.toCollection(LinkedHashSet::new));
        System.out.println(set);

        LinkedHashSet<String> fromSet = artists.stream()
                .map(artist -> artist.getFrom())
                .collect(Collectors.toCollection(LinkedHashSet::new));
        System.out.println(fromSet);

    }

    @Test
    @DisplayName("collect(joining())操作")
    public void test05() {
        List<Artist> artists = Artist.createArtists(10);

        // 将Artist名字串联
        String namesStr  = artists.stream()
                .map(Artist::getName)
                .collect(Collectors.joining(","));

        System.out.println(namesStr);

    }

    @Test
    @DisplayName("collect(groupBy())操作")
    public void test06(){

        List<Artist> artists = Artist.createArtists(10);

        // 根据from字段分组
        Map<String, List<Artist>> fromMap = artists.stream()
                .collect(Collectors.groupingBy(Artist::getFrom));

        System.out.println(fromMap);

        //artists.stream().collect(Collectors.groupingBy(Artist::getFrom,
                //Collectors.mapping(Artist::getFrom, Artist::getMembers)));

        // 分类计数
        Map<String, Long> fromCount = artists.stream().collect(Collectors.groupingBy(Artist::getFrom, Collectors.counting()));
        System.out.println(fromCount);
    }

    @Test
    @DisplayName("自定义收集器：MyCollector")
    public void test07() {
        List<Artist> artists = Artist.createArtists(10);
        List<String> names = artists.stream().map(artist -> artist.getName()).collect(Collectors.toList());

        Multiset<String> nameSet = names.stream().collect(new MyCollector<>());
        System.out.println(nameSet);

        StringJoiner joiner = new StringJoiner(",","[","]");
        String str = joiner.add("tu").add("liang").toString();
        System.out.println(str);
    }

    @Test
    @DisplayName("自定义收集器：ToListCollector")
    public void test08() {
        // 使用ToListCollector 收集器将流转化为List
        Stream<Dish> menuStream = Dish.createDishs(20).stream();
        List<Dish> menuList = menuStream.collect(new ToListCollector<Dish>());
        System.out.println(menuList);
    }

    private Car createCar(Artist a) {
        return new Car(a.getName());
    }

    /**
     *
     */
    public static class Car{
        private String ower;
        private String name;

        public Car(String ower){
            this.ower = ower;
        }

        public Car(String ower, String name) {
            this.ower = ower;
            this.name = name;
        }

        public String getOwer() {
            return ower;
        }

        public void setOwer(String ower) {
            this.ower = ower;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }


    }
}
